package cn.jinjimi.app.main.widget.Behavior;

import android.content.Context;
import android.os.Handler;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;

import cn.jinjimi.app.R;
import cn.jinjimi.app.ui.interfaces.ICollapsedHeightView;
import cn.jinjimi.app.main.widget.MyViewPager;
import cn.jinjimi.app.main.widget.XListView.XListView;

import java.lang.ref.WeakReference;

/**
 * Created by Roy on 2016/12/30.
 */
public class HeaderScrollingBehavior extends CoordinatorLayout.Behavior<MyViewPager> {

    private boolean isScrolling = false;

    private WeakReference<View> dependentView;
    private Scroller scroller;
    private Handler handler;
    private WeakReference<ICollapsedHeightView> mCollapsedHeightView;

    private float mCloseY;
    private float mOpenY;


    public HeaderScrollingBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
        scroller = new Scroller(context);
        handler = new Handler();
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, MyViewPager child, View dependency) {
        if (dependency != null && dependency.getId() == R.id.ll_head) {
            dependentView = new WeakReference<>(dependency);

            View myParent = parent.getRootView();
            if (myParent == null) {
                myParent = parent;
            }
            View collapsedHeightView = myParent.findViewById(R.id.collapsed_height_view);
            if (collapsedHeightView instanceof ICollapsedHeightView) {
                ICollapsedHeightView iCollapsedHeightView = (ICollapsedHeightView) collapsedHeightView;
                mCollapsedHeightView = new WeakReference<ICollapsedHeightView>(iCollapsedHeightView);
            }

            return true;
        }
        return false;
    }

    @Override
    public boolean onLayoutChild(CoordinatorLayout parent, MyViewPager child, int layoutDirection) {
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
        if (lp.height == CoordinatorLayout.LayoutParams.MATCH_PARENT && parent != null) {
            child.layout(0, 0, parent.getWidth(), (int) (parent.getHeight() - getDependentViewCollapsedHeight()));
            return true;
        }
        return super.onLayoutChild(parent, child, layoutDirection);
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, MyViewPager child, View dependency) {
        child.setTranslationY(dependency.getHeight() + dependency.getTranslationY());
        if (mOpenY == 0) {
            mOpenY = child.getTranslationY();
            mCloseY = mOpenY - (dependency.getHeight() - getDependentViewCollapsedHeight());
        } else {
            child.setTouchEnable(child.getTranslationY() == mCloseY || child.getTranslationY() == mOpenY);
        }
        return true;
    }

    @Override // 是否接受处理本次滑动
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, MyViewPager child, View directTargetChild, View target, int nestedScrollAxes) {
        return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;//这里返回true，才会接受到后续滑动事件。
    }

    @Override // 接受处理本次滑动后调用
    public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, MyViewPager child, View directTargetChild, View target, int nestedScrollAxes) {
        scroller.abortAnimation();

        super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, MyViewPager child, View target, int dx, int dy, int[] consumed) {
        if (dy < 0) {
            return;
        }

        View dependentView = getDependentView();
        float newTranslateY = dependentView.getTranslationY() - dy;
        float minHeaderTranslate = -(dependentView.getHeight() - getDependentViewCollapsedHeight());

        if (newTranslateY > minHeaderTranslate) {
            dependentView.setTranslationY(newTranslateY);
            consumed[1] = dy;
        }
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, MyViewPager child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        //进行滑动事件处理
        if (dyUnconsumed > 0) {
            return;
        }

        View dependentView = getDependentView();
        float newTranslateY = dependentView.getTranslationY() - dyUnconsumed;
        final float maxHeaderTranslate = 0;

        if (newTranslateY < maxHeaderTranslate) {
            dependentView.setTranslationY(newTranslateY);
        } else {
        }
    }

    private boolean canPullRefresh = true;

    @Override
    public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, MyViewPager child, View target, float velocityX, float velocityY) {
        //当进行快速滑动
        return onUserStopDragging(velocityY);
    }

    @Override
    public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, MyViewPager child, View target) {
        if (!isScrolling) {
            onUserStopDragging(800);
        }

    }

    private boolean onUserStopDragging(float velocity) {
        canPullRefresh = false;
        View dependentView = getDependentView();
        float translateY = dependentView.getTranslationY();
        float minHeaderTranslate = -(dependentView.getHeight() - getDependentViewCollapsedHeight());

        if (translateY == 0 || translateY == minHeaderTranslate) {
            return false;
        }

        boolean targetState; // Flag indicates whether to expand the content.
        if (Math.abs(velocity) <= 800) {
            if (Math.abs(translateY) < Math.abs(translateY - minHeaderTranslate)) {
                targetState = false;
            } else {
                targetState = true;
            }
            velocity = 800; // Limit velocity's minimum value.
        } else {
            if (velocity > 0) {
                targetState = true;
            } else {
                targetState = false;
            }
        }

        float targetTranslateY = targetState ? minHeaderTranslate : 0;
        scroller.startScroll(0, (int) translateY, 0, (int) (targetTranslateY - translateY), (int) (1000000 / Math.abs(velocity)));
        handler.post(flingRunnable);
        isScrolling = true;

        return true;
    }

    private float getDependentViewCollapsedHeight() {
        if (mCollapsedHeightView != null && mCollapsedHeightView.get() != null) {
            return mCollapsedHeightView.get().getCollapsedHeight();
        }
        return getDependentView().getResources().getDimension(R.dimen.dp_43);
    }

    private View getDependentView() {
        return dependentView.get();
    }

    private Runnable flingRunnable = new Runnable() {
        @Override
        public void run() {
            if (scroller.computeScrollOffset()) {
                getDependentView().setTranslationY(scroller.getCurrY());
                handler.post(this);
            } else {
                isScrolling = false;
                canPullRefresh = getDependentView().getTranslationY() == 0;
            }
        }
    };


    private int mInitialTouchX;
    private int mInitialTouchY;
    @Override
    public boolean onInterceptTouchEvent(CoordinatorLayout parent, MyViewPager child, MotionEvent ev) {
        if (!(getDependentView() instanceof ViewGroup) || ((ViewGroup) getDependentView()).getChildCount() <= 0) {
            return false;
        }
        View childScroll = ((ViewGroup) getDependentView()).getChildAt(0);

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mInitialTouchX = (int) (ev.getX() + 0.5f);
                mInitialTouchY = (int) (ev.getY() + 0.5f);
                break;
            case MotionEvent.ACTION_MOVE:
                final int x = (int) (ev.getX() + 0.5f);
                final int y = (int) (ev.getY() + 0.5f);
                final int dx = x - mInitialTouchX;
                final int dy = y - mInitialTouchY;
                if (Math.abs(dy) > Math.abs(dx) && getDependentView().getTranslationY() == 0 && dy > 0) {
                    return true;
                }
                break;
        }

        float y = child.getTranslationY();
        float evY = ev.getY();
        if (evY > y && (canPullRefresh || getDependentView().getTranslationY() == 0)) {
            canPullRefresh = true;
            if (childScroll instanceof XListView || childScroll instanceof RecyclerView)
                child.onTouchEvent(ev);
        }

        return super.onInterceptTouchEvent(parent, child, ev);
    }

    @Override
    public boolean onTouchEvent(CoordinatorLayout parent, MyViewPager child, MotionEvent ev) {
        if (!(getDependentView() instanceof ViewGroup) || ((ViewGroup) getDependentView()).getChildCount() <= 0) {
            return false;
        }
        View childScroll = ((ViewGroup) getDependentView()).getChildAt(0);
        return childScroll.onTouchEvent(ev);
    }
}
